import {Spin} from "antd";
import React, {FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react";
import {addOkModal, closeModal} from "../../../services/ModalService.tsx";
import {createFetchParams, getObjByRule, isString, strToObject} from "../../../utils";
import {AxiosSer} from "../../../services/HttpService.tsx";
import Config from "../../../Config.tsx";
import {getLanguageById} from "../../../../i18n/i18n.tsx";
import GlobalSearch from "../../../global/GlobalSearch.tsx";
import CTable from "../../../global/table/CTable.tsx";
import useThrottle from "../../../customUse/useThrottle.tsx";
import {showMessage} from "../../../reducer/MsgReducer.tsx";
import {loadMenuChild} from "../../../services/MenuService.tsx";
import {coreDispatch} from "../../../utils/StoreUtil.tsx";
import GlobalBtn from "../../../global/GlobalBtn.tsx";

interface SelectModalProps {
    modalKey: string,
    menuId: string,
    menu: any[],
    method: string,
    search: string,
    tableApi: any,
    otherRender: any,
    selectDataIds: string[],
    data: any[],
    viewName: string
    rowKey: string,
    rowSelection: 'single' | 'multiple',
    autoExpand: boolean | undefined,
    isSelectOnlyData: boolean,
    isTreeTable: boolean | undefined,
    isLazyData: boolean | undefined,
    isInitSearch: boolean | undefined,
    onOk?: Function,
    dataSourceFilter?: Function | undefined,
    init: any,
    isMessBool: boolean
}

const SelectModal: FC<SelectModalProps> = (props) => {

    const cTable: any = useRef();

    const [loading, setLoading] = useState<boolean>(false),
        [tableApi, setTableApi] = useState<object>(),
        [menus, setMenus] = useState(null);

    const dataSource: any = {
        flowData: props.flowData || [],
        checkRows: () => {
            if (cTable.current && cTable.current) {
                return cTable.current.getTableSelectedRows()
            }
        }
    };


    const loadMenus: Function = useCallback(async () => {
        const {menuId, menu = []} = props;
        if (menuId) {
            const data = await loadMenuChild({parentId: menuId, menuType: "BUTTON"});
            coreDispatch("menuReducer/createMenuBtn", data);
            setMenus(data);
        } else if (menu) {
            setMenus(menu);
        }
    }, [props.menuId]);

    const onOk: Function = useThrottle(async () => {
        let data: any[] = cTable.current.getTableSelectedRows();
        if (!data.length && props.isSelectOnlyData) {
            showMessage({
                type: "error",
                msg: getLanguageById("pSelectLeastOne")
            })
            return false;
        }
        let {isMessBool = true} = props
        let fetchParams: any = createFetchParams({...props, selectData: data});
        let result: any;
        setLoading(true);
        if (props.onOk) {
            result = await props.onOk(data, fetchParams, props);
        } else if (!fetchParams.url) {
            result = {
                code: "1",
                data: data
            }
        } else {
            result = await AxiosSer(fetchParams.url, props.method || "POST", {
                ...fetchParams.params,
                [Config.axiosSerMenuKey]: props.menuId
            }, isMessBool);
        }
        setLoading(false);
        result.code == "1" && await closeModal(props.modalKey, async () => {
            return result;
        });
    }, 2000, [props.modalKey, props]);

    useEffect(() => {
        let newTableApi: any = {};
        if (props.tableApi) {
            newTableApi = {
                ...props.tableApi,
            }
            if (props.tableApi.initParams && isString(props.tableApi.initParams)) {
                newTableApi.initParams = strToObject(newTableApi.initParams);
            }
            if (props.tableApi.params) {
                newTableApi.params = getObjByRule(props, props.tableApi.params)
            }
            setTableApi(newTableApi);
        }
    }, [props.tableApi]);

    useEffect(() => {
        loadMenus();
    }, [props.menuId]);

    useEffect(() => {
        addOkModal(props.modalKey, onOk)
    }, []);

    const onSearchTable: Function = useCallback((params: any) => {
        cTable.current.searchTable({...params, page: 1}, true);
    }, []);

    const onReset: Function = useCallback(() => {
        cTable.current.searchTable({page: 1}, false);
    }, []);

    useImperativeHandle(props.init, () => {
        return {
            dataSource,
            setLoading
        }
    });


    const renderSearchDom = useMemo(() => {
        const {search}: { search: string } = props;
        if (!search) {
            return null;
        }
        return <GlobalSearch
            view={search}
            onSearch={onSearchTable}
            onReset={onReset}
            dataSource={dataSource}
        />;
    }, [props.search]);

    const renderBtn: any = useMemo(() => {
        if (!menus || !menus.length) {
            return null;
        }
        return (<GlobalBtn
            menus={menus}
            dataSource={dataSource}
        />);
    }, [menus, props.row]);


    const renderTableDom = useMemo(() => {

        const {
            rowKey = "id",
            viewName,
            selectDataIds = [],
            data,
            rowSelection = "single",
            autoExpand = false,
            isTreeTable = false,
            isLazyData = false,
            isInitSearch = true,
            dataSourceFilter,
            isRowSelectable
        }: {
            rowKey: string,
            viewName: string,
            selectDataIds: string[],
            data: any[],
            rowSelection: 'single' | 'multiple',
            autoExpand: boolean | undefined,
            isTreeTable: boolean | undefined,
            isLazyData: boolean | undefined,
            isInitSearch: boolean | undefined,
            dataSourceFilter?: Function | undefined,
            isRowSelectable?: Function | undefined,
        } = props;

        if (!(data || tableApi) || !viewName) {
            return null
        }

        return (
            <CTable
                otherRenderFn={props.otherRender}
                init={cTable}
                view={viewName}
                tableApi={tableApi}
                dataSource={data}
                selectIds={selectDataIds}
                rowKey={rowKey}
                autoExpand={autoExpand}
                height={500}
                rowSelection={rowSelection}
                hasCheckbox={true}
                dataSourceFilter={dataSourceFilter}
                isInitSearch={isInitSearch}
                isTreeTable={isTreeTable}
                isLazyData={isLazyData}
                isRowSelectable={isRowSelectable}
            />
        )
    }, [props, tableApi]);

    const renderSelectModal = useMemo(() => {
        return (
            <Spin spinning={loading}>
                {renderSearchDom}
                {renderTableDom}
            </Spin>
        )
    }, [props, tableApi, loading]);

    return (renderSelectModal);
};

export default SelectModal;